/*
 * main.cpp
 *
 *  Created on: 18/05/2010
 *      Author: Jorge Antonio García Galicia
 */
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <GL/glut.h>

#include "geometry/Vector3D.h"
#include "physics/Particle.h"
#include "physics/EulerIntegrator.h"
#include "physics/RungeKuttaIntegrator.h"
#include "graphics/Sphere.h"

#define MUNDO 100.0f   // Tope de las coordenados de el mundo
#define DT 0.1f

using namespace std;
using namespace geometry;
using namespace physics;
using namespace graphics;

void redimensiona(GLsizei w, GLsizei h);
void dibuja(void);
void inicializa(void);
void tecladoEspecial(int key, int mx, int my);
void funcionTiempo(void);
void moverEscena(void);
void teclado(unsigned char key, int mx, int my);
float grad2Radians(float);
void drawCanon();

float tiempo, power, angle;
bool shoot;
Particle bala;
Sphere vBala(5.0);

int main (int argc, char* argv[]) {

	glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(400, 400);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Canon War");
    inicializa();
    /** Funciones de callback */
    glutSpecialFunc(tecladoEspecial);
    glutDisplayFunc(dibuja);
    glutReshapeFunc(redimensiona);
    glutKeyboardFunc(teclado);
    //glutIdleFunc(funcionTiempo);
    glutMainLoop();

    return 0;
}

void inicializa(void)
{
     glClearColor(1.0, 1.0, 1.0, 1.0);
     glEnable(GL_DEPTH_TEST);
     tiempo = 0.0f;
     Vector3D cero(0, 0, 0);
     shoot = false;
     power = 300.0;
     angle = 45.0;

     //Inicializamos las particulas
     bala.setPosition(Vector3D(-MUNDO, -MUNDO, 0.0));
     bala.setVelocity(cero);
     bala.setForce(cero);
     bala.setMass(1.0);

     //Inicializamos los objetos graficos
     vBala.setColor(Vector3D(0.0, 1.0, 0.0));
}

void redimensiona(GLsizei w, GLsizei h) {
    GLfloat aspectRatio;

    if (h == 0)
       h = 1;

    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    aspectRatio = (GLfloat)w / (GLfloat)h;

    if (w <= h)
       glOrtho(-MUNDO, MUNDO, -MUNDO / aspectRatio, MUNDO / aspectRatio, MUNDO, -MUNDO);
    else
       glOrtho(-MUNDO * aspectRatio, MUNDO * aspectRatio, -MUNDO, MUNDO, MUNDO, -MUNDO);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void tecladoEspecial(int key, int mx, int my) {
	switch(key) {
		case GLUT_KEY_LEFT:
			power -= 10.0;
		break;

		case GLUT_KEY_RIGHT:
			power += 10.0;
		break;

		case GLUT_KEY_UP:
			angle += 1.0;
		break;

		case GLUT_KEY_DOWN:
			angle -= 1.0;
		break;
	}
	cout << "Angulo: " << angle << " Potencia: " << power << endl;
	glutPostRedisplay();
}

void funcionTiempo() {
	tiempo += DT;
	glutPostRedisplay();
}

void dibuja () {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	moverEscena();
	vBala.setCenter(bala.getPosition());

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	drawCanon();
	vBala.draw();

	glutSwapBuffers();

}

void moverEscena() {
	Vector3D gravity(0, -9.8, 0);
	EulerIntegrator e(DT);

	bala.emptyForce();

	//Preguntamos si hay disparo
	if (shoot) {
		tiempo = 0.0;
		bala.emptyVelocity();
		bala.setPosition(Vector3D(-MUNDO, -MUNDO, 0.0));
		bala.addForce(Vector3D(power * cos(grad2Radians(angle)), power * sin(grad2Radians(angle)), 0.0));
		shoot = false;
	}

	bala.addForce(gravity);
	e.integrate(bala);

}

void teclado(unsigned char key, int mx, int my) {
	switch(key) {

	case 27:
		exit(0);
		break;

	case 's':
		shoot = true;
		cout << "¡Fuego!" << endl;
	break;

	case ' ':
		tiempo += DT;
	break;


	default:
		break;
	}
	cout << "Angulo: " << angle << " Potencia: " << power << endl;
	glutPostRedisplay();
}

float grad2Radians (float angleDeg) {
	return 0.017453293f * angleDeg;
}

void drawCanon() {
	glColor3f(1.0, 0.0, 0.0);
	glPushMatrix();
		glTranslatef(-MUNDO, -MUNDO, 0.0);
		glRotatef(angle, 0.0, 0.0, 1.0);
		glScalef(2.0, 1.0, 1.0);
		glutSolidCube(11.0);
	glPopMatrix();
}
